import Vue from 'vue';
import { generateID, deepClone } from '@/utils';
import { basicWidgets } from '@/views/productEdit/components/landingPageWidget/widget-list';

const state = {
  componentData: [], // 编辑model
  activeComponentIndex: undefined, // 当前处于激活组件索引
  componentClick: false, // 当前处于组件点击事件流
  multiSelectIndex: [], // 当前处于多选组件索引
  // 右键菜单列表状态
  contextMenuState: {
    show: false,
    top: 0,
    left: 0
  },
  // 快照记录
  snapshotData: { index: -1, data: [] },
  // 画布大小
  previewer: { width: 750, height: 1600 },
  // 画布缩放比例
  scaleRatio: 1
};
const getters = {
  componentData: (state) => state.componentData,
  componentClick: (state) => state.componentClick,
  activeComponentIndex: (state) => state.activeComponentIndex,
  multiSelectIndex: (state) => state.multiSelectIndex,
  activeComponent: (state) => state.componentData[state.activeComponentIndex],
  isActiveComponent: (state) => (index) => state.activeComponentIndex === index,
  isMultiSelected: (state) => (index) => state.multiSelectIndex.includes(index),
  isLayeredComponent: () => (component) => component?.style?.position === 'absolute',
  zIndexMax: (state) =>
    Math.max.apply(
      null,
      state.componentData.map((component) => component.style.zIndex)
    ),
  contextMenuState: (state) => state.contextMenuState,
  snapshotData: (state) => state.snapshotData,
  snapshotIndex: (state) => state.snapshotData.index,
  scaleRatio: (state) => state.scaleRatio,
  previewer: (state) => state.previewer,
  richText: (state) => state.richText
};
const mutations = {
  // 重置Component
  RESET_COMPONENTDATA(state) {
    console.warn('重置了');
    state.componentData = [];
    state.activeComponentIndex = undefined;
    state.multiSelectIndex = [];
    state.snapshotData = { index: -1, data: [] };
    // 画布大小
    state.previewer = { width: 750, height: 1600 };
    // 画布缩放比例
    state.scaleRatio = 1;
  },
  // 设置编辑model
  SET_COMPONENTDATA(state, data) {
    Vue.set(state, 'componentData', data);
  },
  // 设置正在编辑的快照
  SET_SNAPSHOTDATA(state, snapshotData) {
    Vue.set(state, 'snapshotData', snapshotData);
  },
  // 点击是否为激活（此次点击是否保留组件激活）
  SET_COMPONENTCLICK(state, isInFlow) {
    state.componentClick = isInFlow;
  },
  // 添加组件
  ADD_COMPONENT(state, component) {
    state.componentData.push(component);
    this.commit('component/ACTIVE_COMPONENT', state.componentData.length - 1);
    this.commit('component/RECORD_SNAPSHOT');
  },
  // 删除组件
  DELETE_COMPONENT(state) {
    state.componentData.splice(state.activeComponentIndex, 1);
    this.commit('component/DEPRESS_COMPONENT');
    this.commit('component/RECORD_SNAPSHOT');
  },
  // 层叠/取消层叠组件
  LAYERED_COMPONENT(state) {
    const activeComponent = state.componentData[state.activeComponentIndex];
    const isLayered = this.getters['component/isLayeredComponent'](activeComponent);
    activeComponent.style.position = isLayered ? 'relative' : 'absolute';
    activeComponent.style.width = state.previewer.width;
    activeComponent.style.top = isLayered ? 0 : _calcComponentOffset(activeComponent).top;
    activeComponent.style.left = isLayered ? 0 : _calcComponentOffset(activeComponent).left;
    activeComponent.style.paddingTop = 0;
    activeComponent.style.paddingBottom = 0;
    if (activeComponent.resize) {
      activeComponent.style.paddingLeft = 0;
      activeComponent.style.paddingRight = 0;
    }
  },
  // 复制组件
  COPY_COMPONENT(state) {
    const clone = deepClone(this.getters['component/activeComponent']);
    if (!clone) return;
    clone.id = generateID();
    // 生成不重复的副本名称
    let index = 0;
    let label = '';
    let hasSameLabel = false;
    do {
      index += 1;
      label = clone.label + ` 副本${index}`;
      hasSameLabel = state.componentData.some((widget) => widget.label === label);
    } while (hasSameLabel);
    clone.label = label;
    if (clone.style.position === 'absolute') clone.style.top += 15;
    clone.style.zIndex = this.getters['component/zIndexMax'] + 1;
    state.componentData.splice((state.activeComponentIndex += 1), 0, clone);
    this.commit('component/ACTIVE_COMPONENT', state.activeComponentIndex);
    this.commit('component/RECORD_SNAPSHOT');
  },
  // 激活组件
  ACTIVE_COMPONENT(state, index) {
    state.activeComponentIndex = index;
    state.multiSelectIndex = [index];
    Vue.prototype.$EventBus.$emit('hook:ActiveComponent');
  },
  // 取消激活组件
  DEPRESS_COMPONENT(state) {
    state.activeComponentIndex = undefined;
    Vue.prototype.$EventBus.$emit('hook:ActiveComponent');
    state.multiSelectIndex = [];
    this.commit('component/HIDE_CONTEXTMENU');
  },
  // 多选/取消多选组件
  MULTI_SELECT_COMPONENT(state, index) {
    // 取消单选状态
    state.activeComponentIndex = undefined;
    Vue.prototype.$EventBus.$emit('hook:ActiveComponent');
    // 添加/取消多选
    const i = state.multiSelectIndex.findIndex((i) => i === index);
    if (i === -1) {
      state.multiSelectIndex.push(index);
    } else {
      state.multiSelectIndex.splice(i, 1);
    }
  },
  // 批量设置多选组件
  SET_MULTI_SELECT(state, payload) {
    state.multiSelectIndex = payload;
  },
  // 显示右键菜单
  SHOW_CONTEXTMENU(state, menuState) {
    state.contextMenuState = menuState;
  },
  // 隐藏右键菜单
  HIDE_CONTEXTMENU(state) {
    state.contextMenuState.show = false;
  },
  // 修改激活组件样式
  SET_ACTIVECOMPOENNT_STYLE(state, { key, value }) {
    this.getters['component/activeComponent'].style[key] = value;
  },
  // 上移组件
  MOVEUP_COMPONENT(state) {
    let lastIndex = state.activeComponentIndex - 1;
    while (lastIndex >= 0 && state.componentData[lastIndex].style.position === 'absolute') {
      lastIndex -= 1;
    }
    if (lastIndex === -1) return;
    const temp = state.componentData[lastIndex];
    const activeComponent = this.getters['component/activeComponent'];
    Vue.set(state.componentData, lastIndex, activeComponent);
    Vue.set(state.componentData, state.activeComponentIndex, temp);
    state.activeComponentIndex = lastIndex;
    this.commit('component/RECORD_SNAPSHOT');
  },
  // 下移组件
  MOVEDOWN_COMPONENT(state) {
    let nextIndex = state.activeComponentIndex + 1;
    while (nextIndex < state.componentData.length && state.componentData[nextIndex].style.position === 'absolute') {
      nextIndex += 1;
    }
    if (nextIndex === state.componentData.length) return;
    const temp = state.componentData[nextIndex];
    const activeComponent = this.getters['component/activeComponent'];
    Vue.set(state.componentData, nextIndex, activeComponent);
    Vue.set(state.componentData, state.activeComponentIndex, temp);
    state.activeComponentIndex = nextIndex;
    this.commit('component/RECORD_SNAPSHOT');
  },
  // 上移一层
  LAYERUP_COMPONENT(state, index) {
    const activeComponent =
      index === undefined ? this.getters['component/activeComponent'] : state.componentData[index];
    const componentData = state.componentData;
    const activeComponentZIndex = activeComponent.style.zIndex;
    const zIndexMax = this.getters['component/zIndexMax'];
    // 已作为顶层唯一元素 return;
    if (
      activeComponentZIndex === zIndexMax &&
      componentData.filter((component) => component.style.zIndex === zIndexMax).length === 1
    )
      return;
    // 是否有其它组件也处于当前zIndex
    const hasSameZIndex = getSameZIndex(activeComponentZIndex, componentData);
    if (!hasSameZIndex)
      componentData.forEach((component) => {
        component.style.zIndex > activeComponentZIndex && (component.style.zIndex -= 1);
      });
    activeComponent.style.zIndex += 1;
    index === undefined && this.commit('component/RECORD_SNAPSHOT');
  },
  // 下移一层
  LAYERDOWN_COMPONENT(state, index) {
    const activeComponent =
      index === undefined ? this.getters['component/activeComponent'] : state.componentData[index];
    const componentData = state.componentData;
    const activeComponentZIndex = activeComponent.style.zIndex;
    // 已作为底层唯一元素 return;
    if (activeComponentZIndex === 1 && componentData.filter((component) => component.style.zIndex === 1).length > 1) {
      componentData.forEach((component, index) => {
        if (index === state.activeComponentIndex) return;
        component.style.zIndex += 1;
      });
      return;
    }
    // 是否有其它组件也处于当前zIndex
    const hasSameZIndex = getSameZIndex(activeComponentZIndex, componentData);
    if (!hasSameZIndex)
      componentData.forEach((component) => {
        component.style.zIndex > activeComponentZIndex && (component.style.zIndex -= 1);
      });
    activeComponent.style.zIndex -= 1;
    index === undefined && this.commit('component/RECORD_SNAPSHOT');
  },
  // 置顶组件
  STICKY_COMPONENT(state, index) {
    const activeIndex = index === undefined ? state.activeComponentIndex : index;
    const activeComponent = state.componentData[activeIndex];
    const zIndexMax = this.getters['component/zIndexMax'];
    const activeComponentZIndex = activeComponent.style.zIndex;
    // 是否有其它组件也处于当前zIndex
    const hasSameZIndex = getSameZIndex(activeComponentZIndex, state.componentData);
    if (hasSameZIndex) {
      activeComponent.style.zIndex = zIndexMax + 1;
    } else {
      state.componentData.forEach((component, index) => {
        if (index === activeIndex) return;
        if (component.style.zIndex > activeComponentZIndex) component.style.zIndex -= 1;
      });
      activeComponent.style.zIndex = zIndexMax;
    }
    index === undefined && this.commit('component/RECORD_SNAPSHOT');
  },
  // 置底组件
  BOTTOM_COMPONENT(state, index) {
    const activeIndex = index === undefined ? state.activeComponentIndex : index;
    const activeComponent = state.componentData[activeIndex];
    const activeComponentZIndex = activeComponent.style.zIndex;
    // 是否有其它组件也处于当前zIndex
    const hasSameZIndex = getSameZIndex(activeComponentZIndex, state.componentData);
    if (hasSameZIndex) {
      state.componentData.forEach((component, index) => {
        if (index === activeIndex) return;
        component.style.zIndex += 1;
      });
    } else {
      state.componentData.forEach((component, index) => {
        if (index === activeIndex) return;
        if (component.style.zIndex < activeComponentZIndex) component.style.zIndex += 1;
      });
    }
    activeComponent.style.zIndex = 1;
    index === undefined && this.commit('component/RECORD_SNAPSHOT');
  },
  // 组合组件
  COMBINE_GROUP(state) {
    // 1. 根据子组件计算组合的宽高位置
    const component = state.componentData.filter((widget, i) => state.multiSelectIndex.includes(i));
    let left = Infinity;
    let right = -Infinity;
    let top = Infinity;
    let bottom = -Infinity;
    component.forEach((component) => {
      const isLayered = this.getters['component/isLayeredComponent'](component);
      const style = isLayered ? component.style : _calcComponentOffset(component);
      if (style.left < left) left = style.left;
      if (style.left + style.width > right) right = style.left + style.width;
      if (style.top < top) top = style.top;
      if (style.top + style.height > bottom) bottom = style.top + style.height;
    });
    // 2. 计算子组件在组合内的位置
    component.forEach((component) => {
      component.id = generateID();
      const style = component.style;
      style.left -= left;
      style.top -= top;
    });
    // 3. 生成并添加组合组件
    const group = deepClone(basicWidgets.find((widget) => widget.component === 'Group'));
    group.id = generateID();
    group.label = _generateGroupLabel(state.componentData);
    group.style.width = right - left;
    group.style.height = bottom - top;
    group.style.top = top;
    group.style.left = left;
    group.style.zIndex = this.getters['component/zIndexMax'] + 1;
    group.config.component = component;
    // 4. 组合组件替代原组件
    const groupIndex = Math.min(...state.multiSelectIndex);
    const list = state.componentData.filter((widget, i) => !state.multiSelectIndex.includes(i));
    list.splice(groupIndex, 0, group);
    state.componentData.splice(0, state.componentData.length, ...list);
    this.commit('component/ACTIVE_COMPONENT', groupIndex);
  },
  // 拆分组件
  SEPARATE_GROUP(state) {
    // 1. 根据组合组件计算子组件位置
    const style = this.getters['component/activeComponent'].style;
    const componentList = this.getters['component/activeComponent'].config.component;
    componentList.forEach((component) => {
      component.id = generateID();
      component.style.top += style.top;
      component.style.left += style.left;
    });
    // 2. 子组件列表替代组合组件
    const groupIndex = state.activeComponentIndex;
    state.componentData.splice(groupIndex, 1, ...componentList);
    this.commit('component/DEPRESS_COMPONENT');
    state.multiSelectIndex = componentList.reduce((arr, comp, i) => {
      arr.push(groupIndex + i);
      return arr;
    }, []);
  },
  // 撤销快照
  BACK_SNAPSHOT() {
    const snapshotData = this.getters['component/snapshotData'];
    if (snapshotData.index === 0) return;
    snapshotData.index -= 1;
    state.componentData = deepClone(snapshotData.data[snapshotData.index]) || [];
  },
  // 恢复快照
  RESTORE_SNAPSHOT() {
    const snapshotData = this.getters['component/snapshotData'];
    if (snapshotData.index + 1 > snapshotData.data.length - 1) return;
    snapshotData.index += 1;
    state.componentData = deepClone(snapshotData.data[snapshotData.index]);
  },
  // 添加快照
  RECORD_SNAPSHOT(state) {
    const snapshotData = this.getters['component/snapshotData'];
    // 此次添加基于撤销的快照，清除无效快照
    if (snapshotData.index < snapshotData.data.length - 1) {
      snapshotData.data.splice(snapshotData.index + 1);
    }
    // 到达上限
    if (snapshotData.data.length === 20) {
      snapshotData.data.shift();
      snapshotData.index -= 1;
    }
    snapshotData.data[++snapshotData.index] = deepClone(state.componentData);
  },
  // 移动组件位置
  MOVE_COMPONENT(state, { x, y }) {
    const maxL = this.getters['component/previewer'].width;
    const maxT = this.getters['component/previewer'].height;
    this.getters['component/multiSelectIndex'].forEach((index) => {
      const component = state.componentData[index];
      if (this.getters['component/isLayeredComponent'](component)) {
        const style = component.style;
        const left = style.left + x;
        const top = style.top + y;
        if (left >= 0 && left <= maxL - style.width) style.left = left;
        if (top >= 0 && top <= maxT - style.height) style.top = top;
      }
    });
  },
  // 画布缩放比例
  SET_SCALERATIO(state, value) {
    state.scaleRatio = value;
  },
  // 设置画布大小
  SET_PREVIEWER(state, value) {
    state.previewer = value;
  },
  // 调整画布宽度
  SET_PREVIEWER_WIDTH(state, value) {
    state.previewer.width = parseInt(value);
  },
  // 调整画布高度
  SET_PREVIEWER_HEIGHT(state, value) {
    state.previewer.height = parseInt(value);
  }
};
const actions = {};

// 判断：当前组件层级是否唯一
function getSameZIndex(activeComponentZIndex, componentData) {
  return componentData.some((component, index) => {
    if (index === state.activeComponentIndex) return false;
    return component.style.zIndex === activeComponentZIndex;
  });
}

// 生成不重复的组合名称
function _generateGroupLabel(componentData) {
  let index = 0;
  let label = '';
  let hasSameName = false;
  do {
    index += 1;
    label = '组合' + index;
    hasSameName = componentData.some((component) => component.label === label);
  } while (hasSameName);
  return label;
}

// 计算非层叠组件的相对画布位置
function _calcComponentOffset(component) {
  const $component = document.querySelector(`[data-id='${component.id}']`);
  return {
    height: component.style.height,
    width: component.style.width,
    top: $component?.offsetTop || 0,
    left: $component?.offsetLeft || 0
  };
}

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
};
